﻿using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.IO;
using System.Text;

namespace 控制台编码切换器
{
    /// <summary>
    /// 通用工具类（含BOM处理功能）
    /// </summary>
    internal static class Utils
    {
        #region BOM处理相关
        /// <summary>
        /// 检测并移除文件的UTF-8 BOM头
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>是否成功移除BOM（true=已移除，false=无BOM或处理失败）</returns>
        public static bool RemoveBomFromFile(string filePath)
        {
            try
            {
                // 读取文件前3字节（BOM标识）
                byte[] bomBytes = new byte[3];
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    int readBytes = fs.Read(bomBytes, 0, 3);
                    // 检查是否为UTF-8 BOM（EF BB BF）
                    if (readBytes != 3 || !(bomBytes[0] == 0xEF && bomBytes[1] == 0xBB && bomBytes[2] == 0xBF))
                    {
                        return false; // 无BOM，无需处理
                    }
                }

                // 读取剩余内容（跳过BOM）
                byte[] contentBytes;
                using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    fs.Seek(3, SeekOrigin.Begin); // 跳过前3字节BOM
                    contentBytes = new byte[fs.Length - 3];
                    fs.Read(contentBytes, 0, contentBytes.Length);
                }

                // 重新写入文件（覆盖原文件，无BOM）
                using (FileStream fs = new FileStream(filePath, FileMode.Create, FileAccess.Write))
                {
                    fs.Write(contentBytes, 0, contentBytes.Length);
                }

                return true; // BOM已移除
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] 移除BOM失败：{ex.Message}");
                return false;
            }
        }
        #endregion

        #region 原有编码配置相关
        /// <summary>
        /// 修改 Windows Terminal 配置（启用 UTF-8 支持）
        /// </summary>
        public static void ModifyWindowsTerminalSettings()
        {
            try
            {
                string settingsPath = Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
                    @"Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json");

                if (!File.Exists(settingsPath))
                {
                    Console.WriteLine($"[WARN] 未找到 Windows Terminal 配置文件: {settingsPath}");
                    return;
                }

                string json = File.ReadAllText(settingsPath, Encoding.UTF8);
                if (json.Contains("\"experimental.useUnicodeUTF8\""))
                {
                    Console.WriteLine("[INFO] Windows Terminal 已启用 UTF-8 支持，无需重复修改");
                    return;
                }

                string patch = "\"experimental.useUnicodeUTF8\": true,";
                string newJson = json.Contains("\"defaults\": {")
                    ? json.Replace("\"defaults\": {", $"\"defaults\": {{\n    {patch}")
                    : json.Replace("\"profiles\": {", $"\"defaults\": {{\n    {patch}\n  }},\n  \"profiles\": {{");

                File.WriteAllText(settingsPath, newJson, Encoding.UTF8);
                Console.WriteLine("[INFO] 已修改 Windows Terminal 配置，请重启 Terminal 生效");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] 修改 Windows Terminal 配置失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 修改注册表（设置 cmd 默认编码为 UTF-8）
        /// </summary>
        public static void ModifyRegistryForCmd()
        {
            try
            {
                using var consoleKey = Registry.CurrentUser.CreateSubKey(@"Console");
                if (consoleKey == null)
                {
                    Console.WriteLine("[ERROR] 无法访问注册表节点 HKCU\\Console");
                    return;
                }

                consoleKey.SetValue("CodePage", 65001, RegistryValueKind.DWord);
                Console.WriteLine("[INFO] 已写入注册表：HKCU\\Console\\CodePage = 65001（UTF-8）");
                CleanSubKeysCodePage();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] 修改注册表失败: {ex.Message}");
            }
        }

        /// <summary>
        /// 清理 Console 子节点的旧编码配置
        /// </summary>
        public static void CleanSubKeysCodePage()
        {
            using var consoleKey = Registry.CurrentUser.OpenSubKey(@"Console", true);
            if (consoleKey == null) return;

            foreach (string subKeyName in consoleKey.GetSubKeyNames())
            {
                using var subKey = Registry.CurrentUser.OpenSubKey($@"Console\{subKeyName}", true);
                if (subKey?.GetValue("CodePage") != null)
                {
                    subKey.DeleteValue("CodePage", false);
                    Console.WriteLine($"[INFO] 已清理注册表子节点：HKCU\\Console\\{subKeyName}\\CodePage");
                }
            }
        }

        /// <summary>
        /// 获取系统默认 OEM 编码页（如 GBK 936）
        /// </summary>
        public static uint GetSystemDefaultOemCodePage()
        {
            try
            {
                using var cmdProcess = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "cmd.exe",
                        Arguments = "/c chcp",
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true,
                        StandardOutputEncoding = Encoding.Default
                    }
                };

                cmdProcess.Start();
                string output = cmdProcess.StandardOutput.ReadLine() ?? string.Empty;
                cmdProcess.WaitForExit();

                if (output.Contains(":"))
                {
                    string codePageStr = output.Split(':')[1].Trim();
                    if (uint.TryParse(codePageStr, out uint codePage))
                    {
                        return codePage;
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[ERROR] 获取系统默认编码失败: {ex.Message}");
            }

            return 936; // 默认返回 GBK 编码页
        }
        #endregion
    }
}